// CS 564:: PROJECT STAGE 5 - Catalog
//
// Caela Northey (caela) 905 653 2238
// Colin Laska   (laska) 906 150 7258

#include "catalog.h"

// 1) make sure that a relation with the same name doesn't already exist
//    by using the getInfo() function
// 2) add a tuple to the relcat relation by filling in an instance of
//    the RelDesc structure above and then invoking the
//    RelCatalog::addInfo() method. 
// 3) for each of the attrCnt attributes, invoke AttrCatalog::addInfo()
//    method of the attribute catalog table (referred to by the global
//    variable attrCat), passing the appropriate attribute information
//    from the attrList[] array as an instance of the AttrDesc structure
// 4) create a HeapFile instance to hold tuples of the relation (give it
//    a string that is the relation name).
const Status RelCatalog::createRel(const string & relation, 
				   const int attrCnt,
				   const attrInfo attrList[])
{
  Status status;
  RelDesc rd;
  AttrDesc ad;

  if (relation.empty() || attrCnt < 1)
    return BADCATPARM;

  if (relation.length() >= sizeof rd.relName)
    return NAMETOOLONG;

  //check if name already exists
  if (RelCatalog::getInfo(relation, rd) != RELNOTFOUND)
  {
    return RELEXISTS;
  }

  //add name/attrCnt info to relCat via RelDesc
  strcpy(rd.relName, relation.c_str());
  rd.attrCnt = attrCnt;
  status = relCat->addInfo(rd);
  if (status != OK){
    return status;
  }

  //add attributes to attrCat
  //RECALL:
  // typedef struct {
  //   char relName[MAXNAME];           // relation name
  //   char attrName[MAXNAME];          // attribute name
  //   int  attrType;                   // INTEGER, FLOAT, or STRING
  //   int  attrLen;                    // length of attribute in bytes
  //   void *attrValue;                 // ptr to binary value
  // } attrInfo; 
  uint attr_size = 0;

  for (int i = 0; i < attrCnt; i++){

  //check if name already exists
    if (attrCat->getInfo(attrList[i].relName, attrList[i].attrName, ad) != ATTRNOTFOUND)
    {
      relCat->destroyRel(attrList[i].relName);
      return DUPLATTR;
    }

    strcpy(ad.relName, attrList[i].relName);
    strcpy(ad.attrName, attrList[i].attrName);
    if (i == 0){
      ad.attrOffset = 0;
    }else{
      ad.attrOffset += attrList[i-1].attrLen; //size of prev attr
    }

    ad.attrType = attrList[i].attrType;
    ad.attrLen = attrList[i].attrLen;         //size of curr attr

    // Check attribute tuple length
    attr_size += attrList[i].attrLen;         //size of curr attr
    if (attr_size >= PAGESIZE){
      relCat->destroyRel(attrList[i].relName);
      return ATTRTOOLONG;
    }

    status = attrCat->addInfo(ad);
    if (status != OK){
        return status;
    }
  }

  // create HeapFile to hold tuples
  status = createHeapFile(relation);

  return status;
}
